﻿//IQFeedMarketDepthBuilder.cs
//Copyright (c) 2013 StockSharp LLC, all rights reserved.
//This code module is part of StockSharp library.
//This code is licensed under the GNU GENERAL PUBLIC LICENSE Version 3.
//See the file License.txt for the license details.
//More info on: http://stocksharp.com

namespace StockSharp.Algo.History.IQFeed
{
	using System;
	using System.Linq;

	using Ecng.Collections;
	using Ecng.Common;

	using StockSharp.BusinessEntities;

	class IQFeedMarketDepthBuilder
	{
		private sealed class QuoteInfo
		{
			public QuoteInfo(Security security)
			{
				Asks = new SynchronizedOrderedDictionary<string, IQFeedQuoteMessage>();
				Bids = new SynchronizedOrderedDictionary<string, IQFeedQuoteMessage>();
				MarketDepth = new MarketDepth(security);
			}

			public SynchronizedOrderedDictionary<string, IQFeedQuoteMessage> Asks { get; private set; }
			public SynchronizedOrderedDictionary<string, IQFeedQuoteMessage> Bids { get; private set; }
			public MarketDepth MarketDepth { get; private set; }
			public DateTime LastChangeTime { get; set; }
		}

		private readonly SynchronizedSet<QuoteInfo> _changedDepths = new SynchronizedSet<QuoteInfo>();
		private readonly SynchronizedDictionary<Security, QuoteInfo> _infos = new SynchronizedDictionary<Security, QuoteInfo>();

		public void Update(Security security, IQFeedQuoteMessage message)
		{
			var info = _infos.SafeAdd(security, s => new QuoteInfo(s));

			info.Asks[message.MarketMaker] = message;
			info.Bids[message.MarketMaker] = message;

			info.LastChangeTime = info.LastChangeTime.Max(message.AskTime).Max(message.BidTime);

			_changedDepths.Add(info);
		}

		public MarketDepth[] GetChanges()
		{
			var items = _changedDepths.CopyAndClear();

			foreach (var item in items)
			{
				var security = item.MarketDepth.Security;

				var asks = item.Asks.Where(i => i.Value.IsAskValid).GroupBy(i => i.Value.Ask).Select(i => new Quote
				{
					Security = security,
					Price = i.Key,
					Volume = i.Sum(v => v.Value.AskVolume),
					OrderDirection = OrderDirections.Sell,
				});

				var bids = item.Bids.Where(i => i.Value.IsBidValid).GroupBy(i => i.Value.Bid).Select(i => new Quote
				{
					Security = security,
					Price = i.Key,
					Volume = i.Sum(v => v.Value.BidVolume),
					OrderDirection = OrderDirections.Buy,
				});

				item.MarketDepth.Update(bids, asks, false, item.LastChangeTime);
			}

			return items.Select(i => i.MarketDepth).ToArray();
		}
	}
}